/*
 * FileNameShortener.java
 *
 * See LICENSE.TXT for the license.
 *
 * (c) 2007 Thomas Krause
 */

package FileNameShortener;

import java.io.File;

/**
 * Some MP3-players have difficulties to display "too much" folders. This problem
 * can be reduced if all folder- and filenames are maximal 12 characters long.
 * So this class/program can be used to truncate the file names.
 * 
 * @author <a href="mailto:krause@informatik.hu-berlin.de>Thomas Krause</a>
 */
public class FileNameShortener 
{
  
  /**
   * Recursivly go through the directory.
   * 
   * @param f The file or directory.
   * @param maxLength The maximal length of the new files.
   * @param beVerbose If true each renaming is logged to stdout.
   * @param shortenTrackNumber
   * @return Number of renamed files.
   */
  public static int performTransformation(File f, int maxLength,
    boolean beVerbose, boolean shortenTrackNumber)
  {
    if(f == null || !f.exists())
      return 0;
    
    int subCount = 0;
    
    if(f.isDirectory())
    {
      File[] sub = f.listFiles();
      
      for(File s : sub)
      {
        subCount += performTransformation(s, maxLength, beVerbose, shortenTrackNumber);
      }
    }
    
    // check for file-name length
    String oldName = f.getName();
    if(shortenTrackNumber)
    {
      String track = oldName.replaceFirst("^([0-9][0-9])([\\. \t-])*", "$1");
      if(!track.equals(oldName))
      {
        File testFile = new File(f.getParent() + "/" + track);
        if(!testFile.exists())
        {
          // first rename
          if(f.renameTo(testFile))
          {
            oldName = track;
            f = testFile;
            if(beVerbose)
            {
              System.out.println("changed track name in: " + f.getAbsolutePath());
            }
          }
          else
          {
            System.err.println("error when trying to rename track in \"" + f.getAbsolutePath() + "\"");
            return subCount;
          }
        }
      }
    }
    
    if(oldName.length() > maxLength)
    {
      int dotPosition = oldName.lastIndexOf(".");
      String partBeforeDot = oldName;        
      String dotPart = "";
      if(dotPosition >= 0)
      {
        partBeforeDot = oldName.substring(0, dotPosition-1);
        dotPart = oldName.substring(dotPosition, oldName.length());
      }
      
      int newNameLength = maxLength - dotPart.length();
      // only proceed if senseful
      if(newNameLength >= 3)
      {
        String newName = partBeforeDot.substring(0, Math.min(newNameLength, partBeforeDot.length()))
          + dotPart;
        
        newName = newName.trim();
        
        // check if already existant
        File newFile = new File(f.getParent() + "/" + newName);
        int i = 0;
        while(newFile.exists() && i < 10)
        {
          newName =  partBeforeDot.substring(0, Math.min(newNameLength, partBeforeDot.length())
            - 1)
          + i
          + dotPart;
          
          newName = newName.trim();
          
          newFile = new File(f.getParent() + "/" + newName);

          i++;                       
        }

        if(newFile.exists())
        {
          System.err.println("There are too much almost identical files" +
            ", could not rename \"" + f.getPath() + "\".");
        }
        else
        {
          // finally rename
          f.renameTo(newFile);
          if(beVerbose)
          {
            System.out.println(f.getAbsolutePath() + " -> " + newFile.getName());
          }
          return subCount + 1;
        }

      }
      else
      {
        System.err.println("File \"" + f.getPath() + "\" wasn't truncated since it would be useless." );
      }
    }
    
    return subCount;
  }
  
  private static void printHelp()
  {
    System.out.println("\n");
    System.out.println("fnshortener (version 02)");
    System.out.println("------------------------------\n");
        
    System.out.println("(c) 2007 Thomas Krause (krause@informatik.hu-berlin.de)\n");
    
    System.out.println("*************************************************************");
    System.out.println("* NEVER USE THIS PROGRAM ON YOUR ORIGINAL MP3 COLLECTION!!! *");
    System.out.println("*             Ugly results will be the effect.              *");
    System.out.println("*************************************************************\n");
    
    System.out.println("Some MP3 mobile players only show a very limited number of directories. " +
      "This behavior sometimes can be improved by not using file- and directory-names longer than 12 characters." +
      "(8.3 format) " +
      "fnshortener (file name shortener) will do this conversion for you. Good luck!.\n");
    
    System.out.println("usage:");
    System.out.println("java -jar fnshortener.jar [options] <path>\n");
    
    System.out.println("options:");
    System.out.println("\t--length=<number>  The maximum length. Default is 12.");
    System.out.println("\t--shorten-track-nr Shorten track numbers (e.g. \"09. - \" -> \"09\")");
    System.out.println("\t--non-verbose      Do not print non-error messages");
    System.out.println("\t--help             Print this help");
  }
  
  {
    
  }
  
  /**
   * @param args the command line arguments
   */
  public static void main(String[] args) 
  {
    boolean beVerbose = true;
    boolean shortTrack = false;
    int maxLength = 12;
    
    for(int i=0; i < args.length - 1; i++)
    {
      if(args[i].equals("--non-verbose"))
      {
        beVerbose = false;
      }
      else if(args[i].startsWith("--length="))
      {
        maxLength = Integer.parseInt(args[i].substring(9));
      }
      else if(args[i].equals("--shorten-track-nr"))
      {
        shortTrack = true;
      }
      else
      {
        System.err.println("Unrecognized option \"" + args[i] + "\". " +
          "Use --help for more information on available commands.");
        return;
      }
    }
    
    if(args.length > 0 && !args[args.length-1].startsWith("-"))
    {
      int count = performTransformation(new File(args[args.length - 1]),
        maxLength, beVerbose, shortTrack);
      if(beVerbose)
      {
        System.out.println("Finished. Renamed " + count + " files or directories.");
      }
      return;
    }
    
    printHelp();
    
  }

}
